package com.kingyea.mobilepolice.apimanage.log;


import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.kingyea.mobilepolice.apimanage.log.bean.OperationLog;
import com.kingyea.mobilepolice.apimanage.log.service.OperationLogService;
import com.kingyea.mobilepolice.apimanage.utils.IpUtil;
import com.kingyea.mobilepolice.apimanage.utils.StateCode;
import com.kingyea.mobilepolice.organization.bean.Organization;
import com.kingyea.mobilepolice.system.Result;
import com.kingyea.mobilepolice.user.bean.User;
import com.kingyea.mobilepolice.user.client.UserServiceClient;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;


/**
 * @author Mr.Lin
 * @version v1.0.0
 * @description SysLog切点类
 * @date Created in 2018-02-27 16:01:07
 */
@Aspect
@Component
@Order(0)
public class OperationLogAspect {
    public static final String SUCCESS = "1";
    public static final String FAILED = "0";
    private static final Logger logger = LoggerFactory.getLogger(OperationLogAspect.class);
    @Autowired
    private OperationLogService operationLogService;
    @Autowired
    private UserServiceClient userServiceClient;


    /**
     * 环绕
     *
     * @param pJoinPoint
     * @param operationLogAnnotation
     */
    @Around(value = "@annotation(operationLogAnnotation)")
    public Object around(ProceedingJoinPoint pJoinPoint, OperationLogAnnotation operationLogAnnotation) throws Throwable {
        OperationLog operationLog = setInfo();
        String operateName = operationLogAnnotation.operateName();
        int operateType = operationLogAnnotation.operateType();
        String module = operationLogAnnotation.module();
        operationLog.setOperateName(operateName);
        operationLog.setOperateType(operateType);
        operationLog.setModule(module);
        return proceedAndSaveLog(pJoinPoint, operationLog);
    }

    /**
     * 设置操作结果
     *
     * @return UserActionLog
     */
    private Object proceedAndSaveLog(ProceedingJoinPoint pJoinPoint, OperationLog operationLog) throws Throwable {
        Object result = null;
        try {
            result = pJoinPoint.proceed();
            operationLog.setOperateResult(OperationLogAspect.SUCCESS);
            operationLog.setResultCode(StateCode.OPERATION_SUCCESS);
            Object[] data = pJoinPoint.getArgs();
            List<Object> dataList = Lists.newArrayList(data);
            dataList = dataList.stream().filter(d -> !(d instanceof ServletRequest)).collect(Collectors.toList());
            operationLog.setOperateCondition(JSON.toJSONString(dataList));
            return result;
        } catch (Throwable e) {
            operationLog.setResultCode(StateCode.SYSTEM_ERROR);
            operationLog.setOperateResult(OperationLogAspect.FAILED);
            throw e;
        } finally {
            try {

                operationLogService.asyncSave(operationLog);
            } catch (Throwable e) {
                e.printStackTrace();
                logger.error(e.getLocalizedMessage());
                // 这个 日志记录插入 操作异常 暂时不外抛了
            }
        }
    }

    /**
     * 设置日志基础信息
     *
     * @return UserActionLog
     */
    private OperationLog setInfo() throws Exception {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        OperationLog userActionLog = new OperationLog();
        Result<User> userResult = userServiceClient.getCurrentUserInfo();
        if (userResult != null && userResult.getData() != null) {
            User user = userResult.getData();
            userActionLog.setUserSerialNo(user.getUserId());
            userActionLog.setUserName(user.getName());
            Result<Organization> orgResult = userServiceClient.getOrgBySerialNo(user.getOrgSerialNo());
            if (orgResult != null && orgResult.getData() != null) {
                userActionLog.setOrganization(orgResult.getData().getName());
            }
            userActionLog.setOrganizationId(user.getOrgSerialNo());
        }

        userActionLog.setOperateTime(new Date());

        userActionLog.setTerminalId(IpUtil.getRealIp(request));
        return userActionLog;
    }
}
